<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Jinja2 多用户函数管理与对话演示</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" data-name="vs/editor/editor.main" href="https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min/vs/editor/editor.main.min.css">
    <style>
    #templateEditor { height: 100%; min-height: 350px; border: 1px solid #ccc; }
    .chat-box { max-height: 480px; min-height: 300px; overflow-y: auto; background: #f8f9fa; padding: 1em; border-radius: 8px; margin-bottom: 0; }
    .chat-msg { display: flex; margin-bottom: 10px; }
    .chat-msg.user { justify-content: flex-end; }
    .chat-msg.ai { justify-content: flex-start; }
    .chat-bubble { max-width: 70%; padding: 10px 16px; border-radius: 16px; }
    .chat-msg.user .chat-bubble { background: #007bff; color: #fff; }
    .chat-msg.ai .chat-bubble { background: #e9ecef; color: #333; }
    .input-group { z-index: 10; box-shadow: 0 -2px 8px rgba(0,0,0,0.03); }
    .template-header { display: flex; align-items: center; gap: 1em; }
    .template-header .form-select { width: auto; min-width: 180px; }
    .modal { display: none; position: fixed; z-index: 9999; left: 0; top: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.2); }
    .modal-dialog { margin: 10vh auto; }
    </style>
</head>
<body class="bg-light">
<div class="container-fluid py-4">
    <div class="row mb-3" style="height: 600px;">
        <div class="col-md-6 d-flex flex-column" style="height: 100%;">
            <div class="template-header mb-2">
                <h5 class="mb-0">输入模板</h5>
                <button class="btn btn-outline-primary btn-sm" onclick="saveTemplate()">保存模板</button>
                <button class="btn btn-outline-info btn-sm" onclick="showAIGenModal()">AI生成模板</button>
                <select id="templateSelect" class="form-select" onchange="loadTemplate()">
                    <option value="">选择历史模板</option>
                </select>
            </div>
            <div id="templateEditor" style="flex:1 1 auto;"></div>
        </div>
        <div class="col-md-6 d-flex flex-column" style="height: 100%;">
            <h5>对话结果
                <button class="btn btn-outline-danger btn-sm float-end" onclick="clearSession()">清除会话</button>
            </h5>
            <div id="chatBox" class="chat-box flex-grow-1 mb-2"></div>
            <div class="input-group" style="position: sticky; bottom: 0; background: #f8f9fa;">
                <input id="questionInput" class="form-control" placeholder="请输入你的问题">
                <button class="btn btn-primary" onclick="sendQuestion()">发送</button>
            </div>
        </div>
    </div>
    <div class="row mb-3">
        <div class="col-md-12">
            <button class="btn btn-success" onclick="addFunc()">添加函数</button>
            <span class="ms-3">当前用户：<select id="userSelect" class="form-select d-inline-block w-auto"></select></span>
        </div>
    </div>
    <div class="row mb-3">
        <div class="col-md-12">
            <h6>当前用户自定义函数</h6>
            <table class="table table-bordered">
                <thead><tr><th>函数名</th><th>操作</th></tr></thead>
                <tbody id="funcTable"></tbody>
            </table>
        </div>
    </div>
</div>
<!-- AI生成模板弹窗 -->
<div class="modal" tabindex="-1" id="aiGenModal">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header"><h5 class="modal-title">AI生成模板</h5></div>
      <div class="modal-body">
        <textarea id="aiGenInput" class="form-control" rows="4" placeholder="请输入你的需求，如：帮我生成一个意图识别的模板"></textarea>
      </div>
      <div class="modal-footer">
        <button class="btn btn-secondary" onclick="hideAIGenModal()">取消</button>
        <button class="btn btn-primary" onclick="aiGenerateTemplate()">生成</button>
      </div>
    </div>
  </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min/vs/loader.min.js"></script>
<script>
let sessionId = Date.now().toString();
let chatHistory = [];
let currentUserId = null;
let templateEditor;
const defaultTemplate = `{% if question %}
  {% set result = gen(question) %}
  AI回复: {{ result }}
{% else %}
  请输入你的问题
{% endif %}`;
require.config({ paths: { 'vs': 'https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min/vs' }});
require(['vs/editor/editor.main'], function() {
    templateEditor = monaco.editor.create(document.getElementById('templateEditor'), {
        value: defaultTemplate,
        language: 'jinja',
        theme: 'vs-light',
        automaticLayout: true
    });
    monaco.languages.registerCompletionItemProvider('jinja', {
        provideCompletionItems: function(model, position) {
            return {
                suggestions: [
                    {label:'gen', kind:monaco.languages.CompletionItemKind.Function, insertText:'gen', detail:'大模型生成'},
                    {label:'gen_stream', kind:monaco.languages.CompletionItemKind.Function, insertText:'gen_stream', detail:'流式生成'},
                    {label:'set', kind:monaco.languages.CompletionItemKind.Keyword, insertText:'set', detail:'变量赋值'},
                    {label:'if', kind:monaco.languages.CompletionItemKind.Keyword, insertText:'if', detail:'条件'},
                    {label:'elif', kind:monaco.languages.CompletionItemKind.Keyword, insertText:'elif', detail:'条件'},
                    {label:'else', kind:monaco.languages.CompletionItemKind.Keyword, insertText:'else', detail:'条件'},
                    {label:'block', kind:monaco.languages.CompletionItemKind.Keyword, insertText:'block', detail:'隐藏块'},
                    {label:'append', kind:monaco.languages.CompletionItemKind.Function, insertText:'append', detail:'追加'},
                    {label:'dictget', kind:monaco.languages.CompletionItemKind.Function, insertText:'dictget', detail:'字典取值'},
                    {label:'from_json', kind:monaco.languages.CompletionItemKind.Function, insertText:'from_json', detail:'JSON转对象'},
                ]
            };
        }
    });
    loadUserTemplates();
});
function getTemplateValue() {
    return templateEditor ? templateEditor.getValue() : '';
}
function loadUsers() {
    fetch('/users').then(r=>r.json()).then(users=>{
        const sel = document.getElementById('userSelect');
        sel.innerHTML = '';
        users.forEach(u=>{
            const opt = document.createElement('option');
            opt.value = u.id;
            opt.textContent = u.username;
            sel.appendChild(opt);
        });
        if(users.length>0) {
            sel.value = users[0].id;
            currentUserId = users[0].id;
            loadFuncs();
            loadUserTemplates();
        }
    });
}
function addFunc() {
    window.location.href = `/static/edit_func.html?user_id=${currentUserId}`;
}
document.getElementById('userSelect').onchange = function() {
    currentUserId = this.value;
    loadFuncs();
    loadUserTemplates();
}
function loadFuncs() {
    fetch(`/user_functions?user_id=${currentUserId}`).then(r=>r.json()).then(funcs=>{
        const tb = document.getElementById('funcTable');
        tb.innerHTML = '';
        funcs.forEach(f=>{
            const tr = document.createElement('tr');
            tr.innerHTML = `<td>${f.func_name}</td><td><button class='btn btn-primary btn-sm' onclick='editFunc(${f.id})'>编辑</button> <button class='btn btn-danger btn-sm' onclick='delFunc(${f.id})'>删除</button></td>`;
            tb.appendChild(tr);
        });
    });
}
function editFunc(id) {
    window.location.href = `/static/edit_func.html?id=${id}&user_id=${currentUserId}`;
}
function delFunc(id) {
    if(!confirm('确定删除？')) return;
    fetch('/user_functions', {method:'DELETE',headers:{'Content-Type':'application/json'},body:JSON.stringify({user_id:currentUserId,id})})
    .then(r=>r.json()).then(res=>{loadFuncs();});
}
function sendQuestion() {
    const question = document.getElementById('questionInput').value.trim();
    if(!question) return;
    addChatMsg('user', question);
    chatHistory.push({role: 'user', content: question});
    runTemplateWithQuestion(question);
    document.getElementById('questionInput').value = '';
}
function addChatMsg(role, text) {
    const chatBox = document.getElementById('chatBox');
    const msgDiv = document.createElement('div');
    msgDiv.className = 'chat-msg ' + (role === 'user' ? 'user' : 'ai');
    const bubble = document.createElement('div');
    bubble.className = 'chat-bubble';
    bubble.textContent = text;
    msgDiv.appendChild(bubble);
    chatBox.appendChild(msgDiv);
    chatBox.scrollTop = chatBox.scrollHeight;
}
function runTemplateWithQuestion(question) {
    const template = getTemplateValue();
    fetch('/run', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({template, user_id: currentUserId, question, history: chatHistory, session_id: sessionId})
    })
    .then(r=>r.json())
    .then(res=>{
        addChatMsg('ai', res.result);
        chatHistory.push({role: 'ai', content: res.result});
    });
}
function clearSession() {
    sessionId = Date.now().toString();
    chatHistory = [];
    document.getElementById('chatBox').innerHTML = '';
}
function saveTemplate() {
    const name = prompt('请输入模板名称');
    if (!name) return;
    const content = getTemplateValue();
    fetch('/save_template', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({user_id: currentUserId, name, content})
    }).then(r=>r.json()).then(res=>{
        if(res.success) {
            alert('模板保存成功');
            loadUserTemplates();
        } else {
            alert('保存失败: ' + (res.error || '未知错误'));
        }
    });
}
function loadUserTemplates() {
    if (!currentUserId) return;
    fetch(`/user_templates?user_id=${currentUserId}`).then(r=>r.json()).then(templates=>{
        const sel = document.getElementById('templateSelect');
        sel.innerHTML = '<option value="">选择历史模板</option>';
        templates.forEach(t=>{
            const opt = document.createElement('option');
            opt.value = t.id;
            opt.textContent = t.name;
            sel.appendChild(opt);
        });
    });
}
function loadTemplate() {
    const id = document.getElementById('templateSelect').value;
    if (!id) return;
    fetch(`/load_template?id=${id}`).then(r=>r.json()).then(res=>{
        if(res.content) templateEditor.setValue(res.content);
    });
}
// AI生成模板弹窗逻辑
function showAIGenModal() {
  document.getElementById('aiGenModal').style.display = 'block';
}
function hideAIGenModal() {
  document.getElementById('aiGenModal').style.display = 'none';
}
function aiGenerateTemplate() {
  const userPrompt = document.getElementById('aiGenInput').value.trim();
  if (!userPrompt) return;
  fetch('/ai_generate_template', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({user_id: currentUserId, prompt: userPrompt})
  }).then(r=>r.json()).then(res=>{
    if(res.template) {
      templateEditor.setValue(res.template);
      hideAIGenModal();
    } else {
      alert('生成失败: ' + (res.error || '未知错误'));
    }
  });
}
window.onload = loadUsers;
</script>
</body>
</html> 